home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / r_alias.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  19KB  |  754 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_alias.c: routines for setting up to draw alias models
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24. #include "d_local.h"    // FIXME: shouldn't be needed (is needed for patch
  25.                         // right now, but that should move)
  26.  
  27. #define LIGHT_MIN    5        // lowest light value we'll allow, to avoid the
  28.                             //  need for inner-loop light clamping
  29.  
  30. mtriangle_t        *ptriangles;
  31. affinetridesc_t    r_affinetridesc;
  32.  
  33. void *            acolormap;    // FIXME: should go away
  34.  
  35. trivertx_t        *r_apverts;
  36.  
  37. // TODO: these probably will go away with optimized rasterization
  38. mdl_t                *pmdl;
  39. vec3_t                r_plightvec;
  40. int                    r_ambientlight;
  41. float                r_shadelight;
  42. aliashdr_t            *paliashdr;
  43. finalvert_t            *pfinalverts;
  44. auxvert_t            *pauxverts;
  45. static float        ziscale;
  46. static model_t        *pmodel;
  47.  
  48. static vec3_t        alias_forward, alias_right, alias_up;
  49.  
  50. static maliasskindesc_t    *pskindesc;
  51.  
  52. int                r_amodels_drawn;
  53. int                a_skinwidth;
  54. int                r_anumverts;
  55.  
  56. float    aliastransform[3][4];
  57.  
  58. typedef struct {
  59.     int    index0;
  60.     int    index1;
  61. } aedge_t;
  62.  
  63. static aedge_t    aedges[12] = {
  64. {0, 1}, {1, 2}, {2, 3}, {3, 0},
  65. {4, 5}, {5, 6}, {6, 7}, {7, 4},
  66. {0, 5}, {1, 4}, {2, 7}, {3, 6}
  67. };
  68.  
  69. #define NUMVERTEXNORMALS    162
  70.  
  71. float    r_avertexnormals[NUMVERTEXNORMALS][3] = {
  72. #include "anorms.h"
  73. };
  74.  
  75. void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
  76.     stvert_t *pstverts);
  77. void R_AliasSetUpTransform (int trivial_accept);
  78. void R_AliasTransformVector (vec3_t in, vec3_t out);
  79. void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
  80.     trivertx_t *pverts, stvert_t *pstverts);
  81. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
  82.  
  83.  
  84. /*
  85. ================
  86. R_AliasCheckBBox
  87. ================
  88. */
  89. qboolean R_AliasCheckBBox (void)
  90. {
  91.     int                    i, flags, frame, numv;
  92.     aliashdr_t            *pahdr;
  93.     float                zi, basepts[8][3], v0, v1, frac;
  94.     finalvert_t            *pv0, *pv1, viewpts[16];
  95.     auxvert_t            *pa0, *pa1, viewaux[16];
  96.     maliasframedesc_t    *pframedesc;
  97.     qboolean            zclipped, zfullyclipped;
  98.     unsigned            anyclip, allclip;
  99.     int                    minz;
  100.     
  101. // expand, rotate, and translate points into worldspace
  102.  
  103.     currententity->trivial_accept = 0;
  104.     pmodel = currententity->model;
  105.     pahdr = Mod_Extradata (pmodel);
  106.     pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
  107.  
  108.     R_AliasSetUpTransform (0);
  109.  
  110. // construct the base bounding box for this frame
  111.     frame = currententity->frame;
  112. // TODO: don't repeat this check when drawing?
  113.     if ((frame >= pmdl->numframes) || (frame < 0))
  114.     {
  115.         Con_DPrintf ("No such frame %d %s\n", frame,
  116.                 pmodel->name);
  117.         frame = 0;
  118.     }
  119.  
  120.     pframedesc = &pahdr->frames[frame];
  121.  
  122. // x worldspace coordinates
  123.     basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
  124.             (float)pframedesc->bboxmin.v[0];
  125.     basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
  126.             (float)pframedesc->bboxmax.v[0];
  127.  
  128. // y worldspace coordinates
  129.     basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
  130.             (float)pframedesc->bboxmin.v[1];
  131.     basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
  132.             (float)pframedesc->bboxmax.v[1];
  133.  
  134. // z worldspace coordinates
  135.     basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
  136.             (float)pframedesc->bboxmin.v[2];
  137.     basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
  138.             (float)pframedesc->bboxmax.v[2];
  139.  
  140.     zclipped = false;
  141.     zfullyclipped = true;
  142.  
  143.     minz = 9999;
  144.     for (i=0; i<8 ; i++)
  145.     {
  146.         R_AliasTransformVector  (&basepts[i][0], &viewaux[i].fv[0]);
  147.  
  148.         if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
  149.         {
  150.         // we must clip points that are closer than the near clip plane
  151.             viewpts[i].flags = ALIAS_Z_CLIP;
  152.             zclipped = true;
  153.         }
  154.         else
  155.         {
  156.             if (viewaux[i].fv[2] < minz)
  157.                 minz = viewaux[i].fv[2];
  158.             viewpts[i].flags = 0;
  159.             zfullyclipped = false;
  160.         }
  161.     }
  162.  
  163.     
  164.     if (zfullyclipped)
  165.     {
  166.         return false;    // everything was near-z-clipped
  167.     }
  168.  
  169.     numv = 8;
  170.  
  171.     if (zclipped)
  172.     {
  173.     // organize points by edges, use edges to get new points (possible trivial
  174.     // reject)
  175.         for (i=0 ; i<12 ; i++)
  176.         {
  177.         // edge endpoints
  178.             pv0 = &viewpts[aedges[i].index0];
  179.             pv1 = &viewpts[aedges[i].index1];
  180.             pa0 = &viewaux[aedges[i].index0];
  181.             pa1 = &viewaux[aedges[i].index1];
  182.  
  183.         // if one end is clipped and the other isn't, make a new point
  184.             if (pv0->flags ^ pv1->flags)
  185.             {
  186.                 frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
  187.                        (pa1->fv[2] - pa0->fv[2]);
  188.                 viewaux[numv].fv[0] = pa0->fv[0] +
  189.                         (pa1->fv[0] - pa0->fv[0]) * frac;
  190.                 viewaux[numv].fv[1] = pa0->fv[1] +
  191.                         (pa1->fv[1] - pa0->fv[1]) * frac;
  192.                 viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
  193.                 viewpts[numv].flags = 0;
  194.                 numv++;
  195.             }
  196.         }
  197.     }
  198.  
  199. // project the vertices that remain after clipping
  200.     anyclip = 0;
  201.     allclip = ALIAS_XY_CLIP_MASK;
  202.  
  203. // TODO: probably should do this loop in ASM, especially if we use floats
  204.     for (i=0 ; i<numv ; i++)
  205.     {
  206.     // we don't need to bother with vertices that were z-clipped
  207.         if (viewpts[i].flags & ALIAS_Z_CLIP)
  208.             continue;
  209.  
  210.         zi = 1.0 / viewaux[i].fv[2];
  211.  
  212.     // FIXME: do with chop mode in ASM, or convert to float
  213.         v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
  214.         v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
  215.  
  216.         flags = 0;
  217.  
  218.         if (v0 < r_refdef.fvrectx)
  219.             flags |= ALIAS_LEFT_CLIP;
  220.         if (v1 < r_refdef.fvrecty)
  221.             flags |= ALIAS_TOP_CLIP;
  222.         if (v0 > r_refdef.fvrectright)
  223.             flags |= ALIAS_RIGHT_CLIP;
  224.         if (v1 > r_refdef.fvrectbottom)
  225.             flags |= ALIAS_BOTTOM_CLIP;
  226.  
  227.         anyclip |= flags;
  228.         allclip &= flags;
  229.     }
  230.  
  231.     if (allclip)
  232.         return false;    // trivial reject off one side
  233.  
  234.     currententity->trivial_accept = !anyclip & !zclipped;
  235.  
  236.     if (currententity->trivial_accept)
  237.     {
  238.         if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
  239.         {
  240.             currententity->trivial_accept |= 2;
  241.         }
  242.     }
  243.  
  244.     return true;
  245. }
  246.  
  247.  
  248. /*
  249. ================
  250. R_AliasTransformVector
  251. ================
  252. */
  253. void R_AliasTransformVector (vec3_t in, vec3_t out)
  254. {
  255.     out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
  256.     out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
  257.     out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
  258. }
  259.  
  260.  
  261. /*
  262. ================
  263. R_AliasPreparePoints
  264.  
  265. General clipped case
  266. ================
  267. */
  268. void R_AliasPreparePoints (void)
  269. {
  270.     int            i;
  271.     stvert_t    *pstverts;
  272.     finalvert_t    *fv;
  273.     auxvert_t    *av;
  274.     mtriangle_t    *ptri;
  275.     finalvert_t    *pfv[3];
  276.  
  277.     pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
  278.     r_anumverts = pmdl->numverts;
  279.      fv = pfinalverts;
  280.     av = pauxverts;
  281.  
  282.     for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)
  283.     {
  284.         R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);
  285.         if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
  286.             fv->flags |= ALIAS_Z_CLIP;
  287.         else
  288.         {
  289.              R_AliasProjectFinalVert (fv, av);
  290.  
  291.             if (fv->v[0] < r_refdef.aliasvrect.x)
  292.                 fv->flags |= ALIAS_LEFT_CLIP;
  293.             if (fv->v[1] < r_refdef.aliasvrect.y)
  294.                 fv->flags |= ALIAS_TOP_CLIP;
  295.             if (fv->v[0] > r_refdef.aliasvrectright)
  296.                 fv->flags |= ALIAS_RIGHT_CLIP;
  297.             if (fv->v[1] > r_refdef.aliasvrectbottom)
  298.                 fv->flags |= ALIAS_BOTTOM_CLIP;    
  299.         }
  300.     }
  301.  
  302. //
  303. // clip and draw all triangles
  304. //
  305.     r_affinetridesc.numtriangles = 1;
  306.  
  307.     ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
  308.     for (i=0 ; i<pmdl->numtris ; i++, ptri++)
  309.     {
  310.         pfv[0] = &pfinalverts[ptri->vertindex[0]];
  311.         pfv[1] = &pfinalverts[ptri->vertindex[1]];
  312.         pfv[2] = &pfinalverts[ptri->vertindex[2]];
  313.  
  314.         if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
  315.             continue;        // completely clipped
  316.         
  317.         if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
  318.             (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
  319.         {    // totally unclipped
  320.             r_affinetridesc.pfinalverts = pfinalverts;
  321.             r_affinetridesc.ptriangles = ptri;
  322.             D_PolysetDraw ();
  323.         }
  324.         else        
  325.         {    // partially clipped
  326.             R_AliasClipTriangle (ptri);
  327.         }
  328.     }
  329. }
  330.  
  331.  
  332. /*
  333. ================
  334. R_AliasSetUpTransform
  335. ================
  336. */
  337. void R_AliasSetUpTransform (int trivial_accept)
  338. {
  339.     int                i;
  340.     float            rotationmatrix[3][4], t2matrix[3][4];
  341.     static float    tmatrix[3][4];
  342.     static float    viewmatrix[3][4];
  343.     vec3_t            angles;
  344.  
  345. // TODO: should really be stored with the entity instead of being reconstructed
  346. // TODO: should use a look-up table
  347. // TODO: could cache lazily, stored in the entity
  348.  
  349.     angles[ROLL] = currententity->angles[ROLL];
  350.     angles[PITCH] = -currententity->angles[PITCH];
  351.     angles[YAW] = currententity->angles[YAW];
  352.     AngleVectors (angles, alias_forward, alias_right, alias_up);
  353.  
  354.     tmatrix[0][0] = pmdl->scale[0];
  355.     tmatrix[1][1] = pmdl->scale[1];
  356.     tmatrix[2][2] = pmdl->scale[2];
  357.  
  358.     tmatrix[0][3] = pmdl->scale_origin[0];
  359.     tmatrix[1][3] = pmdl->scale_origin[1];
  360.     tmatrix[2][3] = pmdl->scale_origin[2];
  361.  
  362. // TODO: can do this with simple matrix rearrangement
  363.  
  364.     for (i=0 ; i<3 ; i++)
  365.     {
  366.         t2matrix[i][0] = alias_forward[i];
  367.         t2matrix[i][1] = -alias_right[i];
  368.         t2matrix[i][2] = alias_up[i];
  369.     }
  370.  
  371.     t2matrix[0][3] = -modelorg[0];
  372.     t2matrix[1][3] = -modelorg[1];
  373.     t2matrix[2][3] = -modelorg[2];
  374.  
  375. // FIXME: can do more efficiently than full concatenation
  376.     R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
  377.  
  378. // TODO: should be global, set when vright, etc., set
  379.     VectorCopy (vright, viewmatrix[0]);
  380.     VectorCopy (vup, viewmatrix[1]);
  381.     VectorInverse (viewmatrix[1]);
  382.     VectorCopy (vpn, viewmatrix[2]);
  383.  
  384. //    viewmatrix[0][3] = 0;
  385. //    viewmatrix[1][3] = 0;
  386. //    viewmatrix[2][3] = 0;
  387.  
  388.     R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
  389.  
  390. // do the scaling up of x and y to screen coordinates as part of the transform
  391. // for the unclipped case (it would mess up clipping in the clipped case).
  392. // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
  393. // correspondingly so the projected x and y come out right
  394. // FIXME: make this work for clipped case too?
  395.     if (trivial_accept)
  396.     {
  397.         for (i=0 ; i<4 ; i++)
  398.         {
  399.             aliastransform[0][i] *= aliasxscale *
  400.                     (1.0 / ((float)0x8000 * 0x10000));
  401.             aliastransform[1][i] *= aliasyscale *
  402.                     (1.0 / ((float)0x8000 * 0x10000));
  403.             aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
  404.  
  405.         }
  406.     }
  407. }
  408.  
  409.  
  410. /*
  411. ================
  412. R_AliasTransformFinalVert
  413. ================
  414. */
  415. void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
  416.     trivertx_t *pverts, stvert_t *pstverts)
  417. {
  418.     int        temp;
  419.     float    lightcos, *plightnormal;
  420.  
  421.     av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +
  422.             aliastransform[0][3];
  423.     av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +
  424.             aliastransform[1][3];
  425.     av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +
  426.             aliastransform[2][3];
  427.  
  428.     fv->v[2] = pstverts->s;
  429.     fv->v[3] = pstverts->t;
  430.  
  431.     fv->flags = pstverts->onseam;
  432.  
  433. // lighting
  434.     plightnormal = r_avertexnormals[pverts->lightnormalindex];
  435.     lightcos = DotProduct (plightnormal, r_plightvec);
  436.     temp = r_ambientlight;
  437.  
  438.     if (lightcos < 0)
  439.     {
  440.         temp += (int)(r_shadelight * lightcos);
  441.  
  442.     // clamp; because we limited the minimum ambient and shading light, we
  443.     // don't have to clamp low light, just bright
  444.         if (temp < 0)
  445.             temp = 0;
  446.     }
  447.  
  448.     fv->v[4] = temp;
  449. }
  450.  
  451.  
  452. #if    !id386
  453.  
  454. /*
  455. ================
  456. R_AliasTransformAndProjectFinalVerts
  457. ================
  458. */
  459. void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
  460. {
  461.     int            i, temp;
  462.     float        lightcos, *plightnormal, zi;
  463.     trivertx_t    *pverts;
  464.  
  465.     pverts = r_apverts;
  466.  
  467.     for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
  468.     {
  469.     // transform and project
  470.         zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
  471.                 aliastransform[2][3]);
  472.  
  473.     // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
  474.     // scaled up by 1/2**31, and the scaling cancels out for x and y in the
  475.     // projection
  476.         fv->v[5] = zi;
  477.  
  478.         fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
  479.                 aliastransform[0][3]) * zi) + aliasxcenter;
  480.         fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
  481.                 aliastransform[1][3]) * zi) + aliasycenter;
  482.  
  483.         fv->v[2] = pstverts->s;
  484.         fv->v[3] = pstverts->t;
  485.         fv->flags = pstverts->onseam;
  486.  
  487.     // lighting
  488.         plightnormal = r_avertexnormals[pverts->lightnormalindex];
  489.         lightcos = DotProduct (plightnormal, r_plightvec);
  490.         temp = r_ambientlight;
  491.  
  492.         if (lightcos < 0)
  493.         {
  494.             temp += (int)(r_shadelight * lightcos);
  495.  
  496.         // clamp; because we limited the minimum ambient and shading light, we
  497.         // don't have to clamp low light, just bright
  498.             if (temp < 0)
  499.                 temp = 0;
  500.         }
  501.  
  502.         fv->v[4] = temp;
  503.     }
  504. }
  505.  
  506. #endif
  507.  
  508.  
  509. /*
  510. ================
  511. R_AliasProjectFinalVert
  512. ================
  513. */
  514. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
  515. {
  516.     float    zi;
  517.  
  518. // project points
  519.     zi = 1.0 / av->fv[2];
  520.  
  521.     fv->v[5] = zi * ziscale;
  522.  
  523.     fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
  524.     fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
  525. }
  526.  
  527.  
  528. /*
  529. ================
  530. R_AliasPrepareUnclippedPoints
  531. ================
  532. */
  533. void R_AliasPrepareUnclippedPoints (void)
  534. {
  535.     stvert_t    *pstverts;
  536.     finalvert_t    *fv;
  537.  
  538.     pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
  539.     r_anumverts = pmdl->numverts;
  540. // FIXME: just use pfinalverts directly?
  541.     fv = pfinalverts;
  542.  
  543.     R_AliasTransformAndProjectFinalVerts (fv, pstverts);
  544.  
  545.     if (r_affinetridesc.drawtype)
  546.         D_PolysetDrawFinalVerts (fv, r_anumverts);
  547.  
  548.     r_affinetridesc.pfinalverts = pfinalverts;
  549.     r_affinetridesc.ptriangles = (mtriangle_t *)
  550.             ((byte *)paliashdr + paliashdr->triangles);
  551.     r_affinetridesc.numtriangles = pmdl->numtris;
  552.  
  553.     D_PolysetDraw ();
  554. }
  555.  
  556. /*
  557. ===============
  558. R_AliasSetupSkin
  559. ===============
  560. */
  561. void R_AliasSetupSkin (void)
  562. {
  563.     int                    skinnum;
  564.     int                    i, numskins;
  565.     maliasskingroup_t    *paliasskingroup;
  566.     float                *pskinintervals, fullskininterval;
  567.     float                skintargettime, skintime;
  568.  
  569.     skinnum = currententity->skinnum;
  570.     if ((skinnum >= pmdl->numskins) || (skinnum < 0))
  571.     {
  572.         Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
  573.         skinnum = 0;
  574.     }
  575.  
  576.     pskindesc = ((maliasskindesc_t *)
  577.             ((byte *)paliashdr + paliashdr->skindesc)) + skinnum;
  578.     a_skinwidth = pmdl->skinwidth;
  579.  
  580.     if (pskindesc->type == ALIAS_SKIN_GROUP)
  581.     {
  582.         paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr +
  583.                 pskindesc->skin);
  584.         pskinintervals = (float *)
  585.                 ((byte *)paliashdr + paliasskingroup->intervals);
  586.         numskins = paliasskingroup->numskins;
  587.         fullskininterval = pskinintervals[numskins-1];
  588.     
  589.         skintime = cl.time + currententity->syncbase;
  590.     
  591.     // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
  592.     // values are positive, so we don't have to worry about division by 0
  593.         skintargettime = skintime -
  594.                 ((int)(skintime / fullskininterval)) * fullskininterval;
  595.     
  596.         for (i=0 ; i<(numskins-1) ; i++)
  597.         {
  598.             if (pskinintervals[i] > skintargettime)
  599.                 break;
  600.         }
  601.     
  602.         pskindesc = &paliasskingroup->skindescs[i];
  603.     }
  604.  
  605.     r_affinetridesc.pskindesc = pskindesc;
  606.     r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin);
  607.     r_affinetridesc.skinwidth = a_skinwidth;
  608.     r_affinetridesc.seamfixupX16 =  (a_skinwidth >> 1) << 16;
  609.     r_affinetridesc.skinheight = pmdl->skinheight;
  610. }
  611.  
  612. /*
  613. ================
  614. R_AliasSetupLighting
  615. ================
  616. */
  617. void R_AliasSetupLighting (alight_t *plighting)
  618. {
  619.  
  620. // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
  621. // to clamp off the bottom
  622.     r_ambientlight = plighting->ambientlight;
  623.  
  624.     if (r_ambientlight < LIGHT_MIN)
  625.         r_ambientlight = LIGHT_MIN;
  626.  
  627.     r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
  628.  
  629.     if (r_ambientlight < LIGHT_MIN)
  630.         r_ambientlight = LIGHT_MIN;
  631.  
  632.     r_shadelight = plighting->shadelight;
  633.  
  634.     if (r_shadelight < 0)
  635.         r_shadelight = 0;
  636.  
  637.     r_shadelight *= VID_GRADES;
  638.  
  639. // rotate the lighting vector into the model's frame of reference
  640.     r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
  641.     r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
  642.     r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
  643. }
  644.  
  645. /*
  646. =================
  647. R_AliasSetupFrame
  648.  
  649. set r_apverts
  650. =================
  651. */
  652. void R_AliasSetupFrame (void)
  653. {
  654.     int                frame;
  655.     int                i, numframes;
  656.     maliasgroup_t    *paliasgroup;
  657.     float            *pintervals, fullinterval, targettime, time;
  658.  
  659.     frame = currententity->frame;
  660.     if ((frame >= pmdl->numframes) || (frame < 0))
  661.     {
  662.         Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
  663.         frame = 0;
  664.     }
  665.  
  666.     if (paliashdr->frames[frame].type == ALIAS_SINGLE)
  667.     {
  668.         r_apverts = (trivertx_t *)
  669.                 ((byte *)paliashdr + paliashdr->frames[frame].frame);
  670.         return;
  671.     }
  672.     
  673.     paliasgroup = (maliasgroup_t *)
  674.                 ((byte *)paliashdr + paliashdr->frames[frame].frame);
  675.     pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals);
  676.     numframes = paliasgroup->numframes;
  677.     fullinterval = pintervals[numframes-1];
  678.  
  679.     time = cl.time + currententity->syncbase;
  680.  
  681. //
  682. // when loading in Mod_LoadAliasGroup, we guaranteed all interval values
  683. // are positive, so we don't have to worry about division by 0
  684. //
  685.     targettime = time - ((int)(time / fullinterval)) * fullinterval;
  686.  
  687.     for (i=0 ; i<(numframes-1) ; i++)
  688.     {
  689.         if (pintervals[i] > targettime)
  690.             break;
  691.     }
  692.  
  693.     r_apverts = (trivertx_t *)
  694.                 ((byte *)paliashdr + paliasgroup->frames[i].frame);
  695. }
  696.  
  697.  
  698. /*
  699. ================
  700. R_AliasDrawModel
  701. ================
  702. */
  703. void R_AliasDrawModel (alight_t *plighting)
  704. {
  705.     finalvert_t        finalverts[MAXALIASVERTS +
  706.                         ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
  707.     auxvert_t        auxverts[MAXALIASVERTS];
  708.  
  709.     r_amodels_drawn++;
  710.  
  711. // cache align
  712.     pfinalverts = (finalvert_t *)
  713.             (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
  714.     pauxverts = &auxverts[0];
  715.  
  716.     paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
  717.     pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
  718.  
  719.     R_AliasSetupSkin ();
  720.     R_AliasSetUpTransform (currententity->trivial_accept);
  721.     R_AliasSetupLighting (plighting);
  722.     R_AliasSetupFrame ();
  723.  
  724.     if (!currententity->colormap)
  725.         Sys_Error ("R_AliasDrawModel: !currententity->colormap");
  726.  
  727.     r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
  728.             r_recursiveaffinetriangles;
  729.  
  730.     if (r_affinetridesc.drawtype)
  731.     {
  732.         D_PolysetUpdateTables ();        // FIXME: precalc...
  733.     }
  734.     else
  735.     {
  736. #if    id386
  737.         D_Aff8Patch (currententity->colormap);
  738. #endif
  739.     }
  740.  
  741.     acolormap = currententity->colormap;
  742.  
  743.     if (currententity != &cl.viewent)
  744.         ziscale = (float)0x8000 * (float)0x10000;
  745.     else
  746.         ziscale = (float)0x8000 * (float)0x10000 * 3.0;
  747.  
  748.     if (currententity->trivial_accept)
  749.         R_AliasPrepareUnclippedPoints ();
  750.     else
  751.         R_AliasPreparePoints ();
  752. }
  753.  
  754.